package Concurrency2.Chapter03_CAS_Atomic;

import sun.misc.Unsafe;

import java.lang.reflect.Field;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Instruction: 通过Unsafe实现无锁自增并测试结果.
 * Author：@author MaLi
 */
public class T02_UnsafeUsage {
    //定义一个属性

    //通过unsafe在两个线程中修改其属性值, 最后打印最终结果
    static class OptimisticLocking {
        // 待自增的整数共享变量
        private volatile int num = 0; //关键: 多线程之间保证可见
        // 主角: 使用Unsafe直接操作内存
        private static Unsafe unsafe;
        // 内存的地址: 这里使用相对实例对象的偏移量
        private static long valueOffset;

        static {
            //初始化
            try {
                // 在字节码中获取属性
                Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
                theUnsafe.setAccessible(true);
                // 关键1: 获取Unsafe实例
                unsafe = (Unsafe) theUnsafe.get(null);
                // 关键2: 获取要操作属性的address - 偏移量
                valueOffset = unsafe.objectFieldOffset(OptimisticLocking.class.getDeclaredField("num"));
                //如果是静态变量 unsafe.staticFieldOffset(静态变量);
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }

        //使用Unsafe的cas操作, 修改num的值
        public final boolean unSafeCompareAndSet(int oldValue, int newValue) {
            //关键操作: 使用Unsafe的cas
            return unsafe.compareAndSwapInt(this, valueOffset, oldValue, newValue);
            //return unsafe.weakCompareAndSetIntAcquire(this, valueOffset, oldValue, newValue);
        }

        //自旋方式自增
        public void selfPlus() {
            int oldValue = num;
            do {
                //获取当前最新num值
                oldValue = num;
            } while (!unSafeCompareAndSet(oldValue, oldValue + 1));
        }
    }

    // 测试用例: 提交10个并行Task, 每个Task使用自造的selfPlus实现自加1000次, 期望的结果是1万
    public static void main(String[] args) {
        CountDownLatch latch = new CountDownLatch(10);
        OptimisticLocking optimisticLocking = new OptimisticLocking();
        ExecutorService service = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 10; i++) {
            service.submit(() -> {
                for (int j = 0; j < 1000; j++) {
                    optimisticLocking.selfPlus(); //调用自造的Api实现无锁自增
                }
                latch.countDown(); //倒数
            });
        }
        try {
            latch.await();  //让MainThread再次等待所有Task执行完成
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(optimisticLocking.num);  //期望的结果: 10000
        service.shutdownNow();                      //暴力关闭线程池
    }
}
